home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 26 / AACD 26.iso / AACD / Programming / ace_gpl_release / src / ace / c / control.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-10-04  |  17.9 KB  |  740 lines

  1. /* << ACE >>
  2.  
  3.    -- Amiga BASIC Compiler --
  4.  
  5.    ** Parser: control constructs **
  6.    ** Copyright (C) 1998 David Benn
  7.    ** 
  8.    ** This program is free software; you can redistribute it and/or
  9.    ** modify it under the terms of the GNU General Public License
  10.    ** as published by the Free Software Foundation; either version 2
  11.    ** of the License, or (at your option) any later version.
  12.    **
  13.    ** This program is distributed in the hope that it will be useful,
  14.    ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.    ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.    ** GNU General Public License for more details.
  17.    **
  18.    ** You should have received a copy of the GNU General Public License
  19.    ** along with this program; if not, write to the Free Software
  20.    ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  21.  
  22.    Author: David J Benn
  23.      Date: 26th October-30th November, 1st-13th December 1991,
  24.        14th,20th-27th January 1992, 
  25.            2nd-17th, 21st-29th February 1992, 
  26.        1st,13th,14th,22nd,23rd March 1992,
  27.        21st,22nd April 1992,
  28.        2nd,3rd,11th,15th,16th May 1992,
  29.        7th,8th,9th,11th,13th,14th,28th,29th,30th June 1992,
  30.        2nd-8th,14th-19th,26th-29th July 1992,
  31.        1st-3rd,7th,8th,9th August 1992,
  32.        6th,7th December 1992,
  33.        11th,12th,14th,15th,28th February 1993,
  34.        1st,3rd March 1993,
  35.        2nd,5th January 1994,
  36.        20th August 1994,
  37.        4th,9th September 1996
  38. */
  39.  
  40. #include "acedef.h"
  41.  
  42. /* locals */
  43. static    char     *frame_ptr[] = { "(a4)","(a5)" };
  44. static     CODE    *option[255];
  45.  
  46. /* externals */
  47. extern    int    sym;
  48. extern    int    lastsym;
  49. extern    int    obj;
  50. extern    int    typ;
  51. extern    int      lev;
  52. extern    int    storetype;
  53. extern    char       id[MAXIDSIZE]; 
  54. extern    SYM    *curr_item;
  55. extern    CODE    *curr_code;
  56. extern    CODE    *exit_for_cx;
  57. extern    BOOL    end_of_source;
  58. extern    BOOL    have_equal;
  59. extern    BOOL    have_lparen;
  60.  
  61. /* functions */
  62. void block_if(cx1)
  63. CODE *cx1;
  64. {
  65. char labname1[80],lablabel1[80];
  66. char labname2[80],lablabel2[80];
  67. char labname3[80],lablabel3[80];
  68. CODE *cx2;
  69.  
  70.  /* statement block after THEN */
  71.  insymbol();
  72.  do
  73.  {
  74.   statement();
  75.  }
  76.  while ((sym != elsesym) && (sym != endsym) && (!end_of_source));  
  77.        /* ELSE or END IF */
  78.  
  79.    /* ELSE? */
  80.    if (sym == elsesym)
  81.    {
  82.     gen("nop","  ","  ");  /* jump after THEN statement block */
  83.     cx2=curr_code;
  84.  
  85.     /* execute ELSE code section if expression false */
  86.     make_label(labname1,lablabel1);
  87.     gen(lablabel1,"  ","  ");
  88.     change(cx1,"jmp",labname1,"  ");
  89.     
  90.     insymbol();
  91.     do
  92.     {    
  93.      statement();
  94.     }
  95.     while ((sym != endsym) && (!end_of_source));
  96.  
  97.     insymbol();
  98.     if (sym == ifsym)
  99.     {
  100.      /* branch after THEN */
  101.      make_label(labname2,lablabel2);
  102.      gen(lablabel2,"  ","  ");
  103.      change(cx2,"jmp",labname2,"  ");
  104.      insymbol();
  105.     }
  106.     else _error(15);  /* END IF expected */
  107.    }
  108.    else  
  109.        /* no ELSE */
  110.        {
  111.     insymbol();
  112.     if (sym == ifsym)
  113.         {
  114.       make_label(labname3,lablabel3);
  115.       gen(lablabel3,"  ","  ");
  116.       change(cx1,"jmp",labname3,"  ");
  117.      insymbol();
  118.         }
  119.     else _error(15);  /* END IF expected */
  120.        }
  121. }   
  122.  
  123. void if_statement()
  124. {
  125. /* IF..THEN..ELSE..
  126.    IF..GOTO..ELSE..
  127.    IF..THEN..ELSE..END IF  [block IF]
  128. */
  129. CODE *cx1,*cx2,*cx[3];
  130. char labname1[80],lablabel1[80];
  131. char labname2[80],lablabel2[80];
  132. char labname3[80],lablabel3[80];
  133. char labname4[80],lablabel4[80];
  134. char buf[50],destbuf[3],idholder[50];
  135. int  targettype=longtype;
  136. int  i,oldobj,oldtyp;
  137. int  exprtype;
  138.  
  139.  insymbol();
  140.  exprtype=expr();
  141.  
  142.  /* make sure it's a LONG! */
  143.  exprtype=make_integer(exprtype);
  144.  for (i=0;i<=2;i++) 
  145.  {
  146.   gen("nop","  ","  ");
  147.   cx[i]=curr_code;
  148.  }
  149.  coerce(&exprtype,&targettype,cx);
  150.  
  151.  if (exprtype == longtype)
  152.  {
  153.   if ((sym == thensym) || (sym == gotosym))
  154.   {
  155.    gen("move.l","(sp)+","d0");
  156.    gen("cmpi.l","#0","d0");
  157.    make_label(labname1,lablabel1);
  158.    gen("bne.s",labname1,"  ");
  159.    gen("nop","  ","  ");  /* jump past THEN code section */
  160.    cx1=curr_code;
  161.    gen(lablabel1,"  ","  "); /* execute THEN code */
  162.  
  163.   if (sym == gotosym) 
  164.      statement();  /* IF..GOTO */
  165.   else  /* IF..THEN */ 
  166.   {    
  167.    /* block-if, implied GOTO or assignment statement? */   
  168.    insymbol();
  169.    if (sym == endofline) { block_if(cx1); return; } /* block IF statement */
  170.    
  171.    if (sym==ident || sym==shortconst || sym==longconst)  /* label? */ 
  172.    {
  173.      /* assume implied GOTO at first */
  174.      if (sym != ident) make_label_from_linenum(sym,id);
  175.      strcpy(buf,id);
  176.      strcat(buf,":\0");
  177.  
  178.      if (!exist(buf,label)) 
  179.         strcpy(destbuf,"* "); /* mark for later label check (see sym.c) */
  180.      else 
  181.         strcpy(destbuf,"  "); /* it's a declared label */
  182.  
  183.      strcpy(idholder,id);  /* save info for possible "jmp" or assign */
  184.      oldobj=obj;
  185.      oldtyp=typ;
  186.  
  187.      insymbol();
  188.     
  189.      /* variable or array element or implicit branch? */
  190.      if (lastsym != ident ||
  191.         (lastsym == ident && 
  192.          sym != equal && sym != lparen && sym != memberpointer)) 
  193.      {
  194.      /* NOT an assignment statement */
  195.     strcpy(id,idholder);  /* restore id */
  196.         gen("jmp",id,destbuf);
  197.      }
  198.      else 
  199.        if (lastsym == ident)
  200.        {
  201.     /* assignment */
  202.     strcpy(id,idholder); /* restore info for assign() */
  203.     obj=oldobj;
  204.     typ=oldtyp;
  205.     if (sym == equal) have_equal=TRUE;
  206.     if (sym == lparen) 
  207.             if (!exist(id,array)) { _error(71); insymbol(); return; } 
  208.     else
  209.          have_lparen=TRUE;
  210.      assign();       
  211.     have_lparen=FALSE;
  212.     have_equal=FALSE;
  213.         if (sym == colon) statement();  /* multi-statement */
  214.        }
  215.     }
  216.     else
  217.        /* not an ident or line number */
  218.        {
  219.         statement();    
  220.         if (sym == colon) statement();  /* multi-statement */
  221.        }  
  222.    } /* END THEN code */
  223.  
  224.    if (sym == elsesym)
  225.    {
  226.     gen("nop","  ","  ");  /* jump past ELSE code section */
  227.     cx2=curr_code;
  228.  
  229.     /* execute ELSE code section if expression false */
  230.     make_label(labname2,lablabel2);
  231.     gen(lablabel2,"  ","  ");
  232.     change(cx1,"jmp",labname2,"  ");
  233.     
  234.     insymbol();
  235.     statement();
  236.     if (sym == colon) statement();  /* multi-statement */
  237.  
  238.     /* unconditional branch after THEN */
  239.     make_label(labname3,lablabel3);
  240.     gen(lablabel3,"  ","  ");
  241.     change(cx2,"jmp",labname3,"  ");
  242.    }
  243.    else
  244.        {
  245.      make_label(labname4,lablabel4);
  246.      gen(lablabel4,"  ","  ");
  247.      change(cx1,"jmp",labname4,"  ");
  248.        }
  249.   }
  250.    else _error(11);
  251.  }
  252.   else _error(4);
  253. }   
  254.  
  255. void while_statement()
  256. {
  257. /* WHILE...WEND */
  258. CODE *cx1,*cx2,*cx[3];
  259. char labname1[80],lablabel1[80];
  260. char labname2[80],lablabel2[80];
  261. char labname3[80],lablabel3[80];
  262. int  targettype=longtype;
  263. int  i;
  264. int  exprtype;
  265.  
  266.  make_label(labname1,lablabel1);
  267.  gen(lablabel1,"  ","  ");
  268.  cx1=curr_code;
  269.  
  270.  insymbol();
  271.  exprtype=expr();
  272.  
  273.  /* make sure it's a LONG! */
  274.  exprtype=make_integer(exprtype);
  275.  for (i=0;i<=2;i++) 
  276.  {
  277.   gen("nop","  ","  ");
  278.   cx[i]=curr_code;
  279.  }
  280.  coerce(&exprtype,&targettype,cx);  /* cx necessary if change from SHORT */
  281.  
  282.  if (exprtype == longtype)
  283.  {
  284.   gen("move.l","(sp)+","d0");
  285.   gen("cmpi.l","#0","d0");
  286.   make_label(labname2,lablabel2);
  287.   gen("bne.s",labname2,"  "); 
  288.   gen("nop","  ","  ");  /* jump out of loop when condition is FALSE */
  289.   cx2=curr_code;
  290.   gen(lablabel2,"  ","  ");  
  291.  
  292.   while ((sym != wendsym) && (!end_of_source)) statement();
  293.  
  294.   if (sym != wendsym) _error(12);
  295.  
  296.   check_for_event();
  297.  
  298.   gen("jmp",labname1,"  ");
  299.  
  300.   make_label(labname3,lablabel3);
  301.   gen(lablabel3,"  ","  ");
  302.   change(cx2,"jmp",labname3,"  ");
  303.  }
  304.  else _error(4);
  305.  
  306.  insymbol();
  307. }
  308.  
  309. void repeat_statement()
  310. {
  311. /* REPEAT...UNTIL */
  312. char labname1[80],lablabel1[80];
  313. char labname2[80],lablabel2[80];
  314. int  exprtype;
  315.  
  316.  make_label(labname1,lablabel1);
  317.  gen(lablabel1,"  ","  ");
  318.  
  319.  insymbol();
  320.  while ((sym != untilsym) && (!end_of_source)) statement();
  321.  
  322.  /* UNTIL condition */
  323.  if (sym == untilsym)
  324.  {
  325.   check_for_event();
  326.   insymbol();
  327.   exprtype = make_integer(expr());
  328.   if (exprtype == shorttype) { make_long(); exprtype=longtype; }
  329.  
  330.   if (exprtype == longtype)
  331.   {
  332.    gen("move.l","(sp)+","d0");
  333.    gen("cmpi.l","#0","d0");
  334.    make_label(labname2,lablabel2);
  335.    gen("bne.s",labname2,"  ");
  336.    gen("jmp",labname1,"  ");    /* loop until condition is TRUE */
  337.    gen(lablabel2,"  ","  ");
  338.   }
  339.   else _error(4);
  340.  }
  341.  else _error(51);
  342. }
  343.  
  344. void case_statement()
  345. {
  346. /* CASE...END CASE */
  347. CODE  *cx;
  348. CODE  *case_ptr[MAXCASES];
  349. char  labname1[80],lablabel1[80];
  350. char  labname2[80],lablabel2[80];
  351. char  case_end_labname[80],case_end_lablabel[80];
  352. SHORT casecount=0;
  353. int   exprtype=undefined;
  354. SHORT i;
  355.  
  356.  insymbol();
  357.  while (sym == endofline) insymbol(); /* skip blank line(s) */
  358.  
  359.  do
  360.  {
  361.   exprtype = make_integer(expr());
  362.   if (exprtype == shorttype) { make_long(); exprtype=longtype; }
  363.  
  364.   if (sym == colon) 
  365.   {
  366.    insymbol();
  367.    
  368.    if (exprtype == longtype)
  369.    {
  370.     gen("move.l","(sp)+","d0");
  371.     gen("cmpi.l","#0","d0");
  372.     make_label(labname1,lablabel1);
  373.     gen("bne.s",labname1,"  "); 
  374.     gen("nop","  ","  ");    /* try next case */
  375.     cx = curr_code;
  376.     gen(lablabel1,"  ","  ");   /* execute code for THIS case */
  377.     
  378.     statement();
  379.     if (sym == colon) statement(); /* multi-statement */
  380.  
  381.     gen("jmp","  ","  ");
  382.     case_ptr[casecount++] = curr_code; /* branch to end of CASE */
  383.     
  384.     /* label for next case */
  385.     make_label(labname2,lablabel2);
  386.     gen(lablabel2,"  ","  ");
  387.     change(cx,"jmp",labname2,"  ");
  388.    }
  389.    else _error(4); /* type mismatch */
  390.   }
  391.   else _error(24); /* colon expected */
  392.  
  393.   while (sym == endofline) insymbol(); /* skip empty line(s) */
  394.  }
  395.  while ((exprtype == longtype) && (sym != endsym) &&
  396.         (casecount < MAXCASES) && (!end_of_source));
  397.  
  398.  /* END CASE */
  399.  if (sym != endsym) 
  400.     _error(52);
  401.  else 
  402.  {
  403.   insymbol();
  404.   if (sym != casesym)
  405.      _error(52);
  406.   else
  407.   {
  408.    make_label(case_end_labname,case_end_lablabel);
  409.    gen(case_end_lablabel,"  ","  ");
  410.    for (i=0;i<casecount;i++) change(case_ptr[i],"jmp",case_end_labname,"  ");
  411.    insymbol();
  412.   }
  413.  }
  414. }
  415.  
  416. int for_assign(addr)
  417. char *addr;
  418. {
  419. char numbuf[80];
  420. SYM  *storage_item;
  421. int  exprtype;
  422.  
  423.  /* does it exist? */
  424.  if (!exist(id,obj)) 
  425.     enter(id,typ,obj,0);
  426.  
  427.  storage_item = curr_item;
  428.  
  429.  /* don't allow a shared variable to be the index */
  430.  if (storage_item->shared) { _error(70); insymbol(); return(undefined); }
  431.  
  432.  /* assign it */
  433.  insymbol(); 
  434.  if (sym == equal) 
  435.  { 
  436.   insymbol(); 
  437.   exprtype = expr();
  438.  
  439.   /* can't use a stringtype! */
  440.   if (exprtype == stringtype) { _error(4); return(undefined); }
  441.   /* expression not successfully parsed */
  442.   if (exprtype == undefined) { _error(0); return(undefined); } 
  443.  
  444.   storetype = assign_coerce(storage_item->type,exprtype);
  445.   if (storetype == notype) 
  446.      _error(4);   /* type mismatch */
  447.   else
  448.      {
  449.       /* get address of object */ 
  450.       itoa(-1*storage_item->address,addr,10);
  451.       strcat(addr,frame_ptr[lev]);
  452.  
  453.       if (storage_item->type == shorttype)
  454.       gen("move.w","(sp)+",addr);
  455.       else
  456.       /* longtype or singletype */
  457.       gen("move.l","(sp)+",addr);
  458.      }
  459.  } 
  460.  else _error(5); /* '=' expected */
  461.  return(storage_item->type);  /* -> type for WHOLE for..next statement */
  462. }
  463.  
  464. void for_statement()
  465. {
  466. /* FOR variable=x to y [STEP [+|-]z]
  467.        Statement Block
  468.    NEXT [variable]
  469. */
  470. CODE *cx1,*cx2;
  471. char labname1[80],lablabel1[80],labname2[80],lablabel2[80];
  472. char labname3[80],lablabel3[80];
  473. char counteraddr[10],limitaddr[10],stepaddr[10];
  474. char for_id[50],cntbuf[10],limbuf[10],stpbuf[10];
  475. int  countertype,limittype,steptype;
  476.  
  477.  /* counter */
  478.  insymbol();
  479.  if (sym != ident) { _error(7); return; }
  480.  strcpy(for_id,id);
  481.  countertype=for_assign(counteraddr);
  482.  
  483.  if (countertype == undefined) return;
  484.  else
  485.  {
  486.   if (sym == tosym)
  487.   {
  488.    /* limit */
  489.    insymbol();
  490.    limittype=expr();
  491.    limittype=assign_coerce(countertype,limittype);
  492.    if (limittype == notype) { _error(4); return; }
  493.    if (limittype == shorttype)
  494.       strcpy(limitaddr,"2(sp)");
  495.    else
  496.       strcpy(limitaddr,"4(sp)");
  497.    if (sym == stepsym)
  498.    {
  499.     /* step */
  500.     insymbol();
  501.     steptype=expr();
  502.     steptype=assign_coerce(countertype,steptype);
  503.     if (steptype == notype) { _error(4); return; }
  504.    }
  505.    else
  506.    {
  507.     switch(countertype)   /* default step = 1 */
  508.     {
  509.      case shorttype  : gen("move.w","#1","-(sp)"); break;
  510.      case longtype   : gen("move.l","#1","-(sp)"); break;
  511.      case singletype : gen("move.l","#$80000041","-(sp)"); break;
  512.     }
  513.     steptype=countertype;
  514.    }
  515.    strcpy(stepaddr,"(sp)");  /* step is on stack top */
  516.  
  517.     /* top of for..next loop */
  518.     make_label(labname1,lablabel1);
  519.     gen(lablabel1,"  ","  ");
  520.     
  521.     /* compare start & limit values */
  522.     strcpy(cntbuf,counteraddr);
  523.     strcpy(limbuf,limitaddr);
  524.     strcpy(stpbuf,stepaddr);
  525.    
  526.     if (countertype == shorttype)
  527.     {
  528.      gen("move.w",cntbuf,"d0");   /* counter */
  529.      gen("move.w",limbuf,"d1");   /* limit */
  530.      gen("cmpi.w","#0",stepaddr);
  531.      make_label(labname2,lablabel2);
  532.      gen("blt",labname2,"  ");
  533.      gen("cmp.w","d1","d0");
  534.      gen("bgt","  ","  ");      /* if STEP +ve -> counter>limit? */
  535.      cx1=curr_code;
  536.      make_label(labname3,lablabel3); /* don't want to do -ve step test too! */
  537.      gen("jmp",labname3,"  ");
  538.      gen(lablabel2,"  ","  ");
  539.      gen("cmp.w","d1","d0");
  540.      gen("blt","  ","  ");      /* if STEP -ve -> counter<limit? */
  541.      cx2=curr_code;
  542.      gen(lablabel3,"  ","  ");    /* label for bypassing -ve step test */
  543.     }
  544.     else
  545.     if (countertype == longtype)
  546.     {
  547.      gen("move.l",cntbuf,"d0");   /* counter */
  548.      gen("move.l",limbuf,"d1");   /* limit */
  549.      gen("cmpi.l","#0",stepaddr);
  550.      make_label(labname2,lablabel2);
  551.      gen("blt",labname2,"  ");
  552.      gen("cmp.l","d1","d0");
  553.      gen("bgt","  ","  ");      /* if STEP +ve -> counter>limit? */
  554.      cx1=curr_code;
  555.      make_label(labname3,lablabel3); /* don't want to do -ve step test too! */
  556.      gen("jmp",labname3,"  ");
  557.      gen(lablabel2,"  ","  ");
  558.      gen("cmp.l","d1","d0");
  559.      gen("blt","  ","  ");      /* if STEP -ve -> counter<limit? */
  560.      cx2=curr_code;
  561.      gen(lablabel3,"  ","  ");    /* label for bypassing -ve step test */
  562.    }
  563.     else
  564.     if (countertype == singletype)
  565.     { 
  566.      gen("moveq","#0","d1");
  567.      gen("move.l",stpbuf,"d0");   /* d0 < d1? (where d1=0) */
  568.      gen("move.l","_MathBase","a6");
  569.      gen("jsr","_LVOSPCmp(a6)","  ");
  570.      enter_XREF("_MathBase");
  571.      enter_XREF("_LVOSPCmp");
  572.      make_label(labname2,lablabel2);
  573.      gen("blt",labname2,"  ");  /* test result of ffp Cmp above */
  574.      gen("move.l",cntbuf,"d0");   /* counter */
  575.      gen("move.l",limbuf,"d1");   /* limit */
  576.      gen("move.l","_MathBase","a6");
  577.      gen("jsr","_LVOSPCmp(a6)","  ");
  578.      gen("bgt","  ","  ");      /* if STEP +ve -> counter>limit? */
  579.      cx1=curr_code;
  580.      make_label(labname3,lablabel3); /* don't want to do -ve step test too! */
  581.      gen("jmp",labname3,"  ");
  582.      gen(lablabel2,"  ","  ");
  583.      gen("move.l",cntbuf,"d0");   /* counter */
  584.      gen("move.l",limbuf,"d1");   /* limit */
  585.      gen("move.l","_MathBase","a6");
  586.      gen("jsr","_LVOSPCmp(a6)","  ");
  587.      gen("blt","  ","  ");      /* if STEP -ve -> counter<limit? */
  588.      cx2=curr_code;
  589.      gen(lablabel3,"  ","  ");    /* label for bypassing -ve step test */
  590.     }
  591.  
  592.     /* statement block */
  593.     while ((sym != nextsym) && (!end_of_source)) statement();
  594.  
  595.     if (sym != nextsym) { _error(17); return; }
  596.  
  597.     /* NEXT -- legally followed by ident, colon or eoln! */
  598.     insymbol();
  599.     if (sym == ident)
  600.     {
  601.      if (strcmp(id,for_id) != 0) { _error(17); insymbol(); return; }
  602.     }
  603.     else
  604.         if ((sym != endofline) && (sym != colon)) 
  605.            { _error(17); insymbol(); return; } 
  606.  
  607.     if (sym != colon) insymbol();   /* return this sym to statement */
  608.  
  609.     /* counter=counter+step */
  610.     switch(steptype)
  611.     {
  612.      case shorttype  :     gen("move.w",stpbuf,"d0");
  613.                  gen("add.w","d0",counteraddr);
  614.             break;
  615.      case longtype   :     gen("move.l",stpbuf,"d0");
  616.                  gen("add.l","d0",counteraddr);
  617.             break;
  618.      case singletype :  gen("move.l",stpbuf,"d0");
  619.             gen("move.l",cntbuf,"d1");
  620.             gen("move.l","_MathBase","a6");
  621.             gen("jsr","_LVOSPAdd(a6)","  ");
  622.             gen("move.l","d0",counteraddr);
  623.                  enter_XREF("_MathBase");
  624.                  enter_XREF("_LVOSPAdd");
  625.             break;
  626.     }
  627.  
  628.     check_for_event();
  629.  
  630.     gen("jmp",labname1,"  ");  /* back to top of loop */
  631.  
  632.     make_label(labname3,lablabel3);
  633.     gen(lablabel3,"  ","  ");
  634.  
  635.     /* POP the step & limit from stack */ 
  636.     if (countertype == shorttype)
  637.        gen("addq","#4","sp");
  638.     else
  639.        gen("addq","#8","sp");
  640.  
  641.     change(cx1,"bgt",labname3,"  ");
  642.     change(cx2,"blt",labname3,"  ");
  643.  
  644.     /* EXIT FOR branch code pointer non-NULL? */
  645.     if (exit_for_cx) 
  646.     {
  647.     change(exit_for_cx,"jmp",labname3,"  ");
  648.     exit_for_cx = NULL;
  649.     }
  650.    }
  651.   }
  652. }
  653.  
  654. void on_branch()
  655. {
  656. char numbuf[40];
  657. char lab[80],lablabel[80];
  658. int  branch;
  659. int  btype;
  660. long i,opt=0;
  661.  
  662. /* ON <integer-expression> GOTO | GOSUB <label> | <line> */
  663.  
  664.  btype=expr();
  665.  if (btype == stringtype) _error(4);
  666.  else
  667.  {
  668.   if (make_integer(btype) == shorttype) make_long();  /* on stack */
  669.  
  670.   if (sym != gotosym && sym != gosubsym) _error(56);
  671.   else
  672.   { 
  673.    branch = sym;  /* GOTO or GOSUB */
  674.  
  675.    do
  676.    {
  677.     insymbol();
  678.     /* label or line-number? */
  679.     if (sym != ident && sym != shortconst && sym != longconst)
  680.        _error(57); 
  681.     else   
  682.     {
  683.      if (sym != ident) make_label_from_linenum(sym,id);
  684.  
  685.      opt++;
  686.  
  687.      sprintf(numbuf,"#%ld",opt);  
  688.      gen("cmpi.l",numbuf,"(sp)");
  689.      make_label(lab,lablabel);
  690.      gen("bne.s",lab,"  ");  /* is opt equal to value on stack? */
  691.  
  692.      gen("addq","#4","sp");  /* remove value from stack before branch */
  693.  
  694.      switch(branch)
  695.      {
  696.       case gotosym  : gen_branch("jmp",id); 
  697.               break;
  698.  
  699.       case gosubsym : gen_branch("jsr",id);
  700.               gen("nop","  ","  ");  /* jump to end of choices */
  701.               option[opt-1] = curr_code;
  702.               break;
  703.      }
  704.  
  705.      gen(lablabel,"  ","  ");
  706.     }
  707.  
  708.     insymbol();
  709.    }
  710.    while (sym == comma);
  711.   }
  712.  
  713.   /* if ON..GOSUB -> branch to end of all choices after GOSUB */
  714.   if (branch == gosubsym && opt > 0) 
  715.      for (i=0;i<opt;i++) change(option[i],"jmp",lab,"  ");
  716.  }
  717. }
  718.  
  719. void block_statement()
  720. {
  721. /*
  722. ** BLOCK..END BLOCK
  723. */
  724.     insymbol(); 
  725.     while (sym == endofline) insymbol(); /* skip blank line(s) */    
  726.  
  727.     while ((sym != endsym) && (!end_of_source)) statement();
  728.  
  729.     if (sym != endsym) 
  730.             _error(80);
  731.      else 
  732.      {
  733.           insymbol();
  734.           if (sym != blocksym) 
  735.             _error(80);
  736.         else
  737.             insymbol();
  738.     }
  739. }
  740.